package office.word.poi;



import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.xwpf.usermodel.PositionInParagraph;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;

import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WordUtil {

    public static void main(String[] args) throws IOException {

        // 模板地址
        String templatePath = "D:\\codespace\\alldemo\\java-test-project\\templates\\测试2.docx";
        // 报告生成地址
        String savePath = "D:\\codespace\\alldemo\\java-test-project\\templates\\测试23.docx";


        // 构建参数集合
        Map<String, Object> params = new HashMap<>();
        params.put("GZTGF", "宁夏中心");
        params.put("GZTGF_01", "北京中心");
        params.put("GZTGF_02", "上海中心");
        params.put("GZTGF_03", "广州中心");

        fillTemplate(templatePath, savePath, params);

        System.out.println("==========================================");
        // 报告与源文件打包
        File data = new File("D:\\codespace\\alldemo\\java-test-project\\templates\\测试.csv");
        File bg = new File("D:\\codespace\\alldemo\\java-test-project\\templates\\测试23.docx");
        List<File> files = new ArrayList<>();
        files.add(data);
        files.add(bg);
        File zipFile = new File("D:\\codespace\\alldemo\\java-test-project\\templates\\测试.zip");
        ZipUtil.toZip(files, zipFile);
    }


    public static void fillTemplate(String templatePath, String savePath, Map<String, Object> params) throws IOException {
        XWPFDocument document = new XWPFDocument(new FileInputStream(templatePath));
        // 循环段落替换变量
        Iterator<XWPFParagraph> paragraphsIterator = document.getParagraphsIterator();
        while (paragraphsIterator.hasNext()) {
            XWPFParagraph next = paragraphsIterator.next();
            replaceParagraph(next, params);
        }
        // 保存报告结果
        saveDocument(document, savePath);
        document.close();
    }

    public static void saveDocument(XWPFDocument document, String savePath) throws IOException {
        OutputStream os = new FileOutputStream(savePath);
        document.write(os);
        os.close();
    }

    public static void replaceParagraph(XWPFParagraph xWPFParagraph, Map<String, Object> parametersMap) {
        List<XWPFRun> runs = xWPFParagraph.getRuns();
        String xWPFParagraphText = xWPFParagraph.getText();
        System.out.println(xWPFParagraphText);
        String regEx = "\\{.+?\\}";
        Pattern pattern = Pattern.compile(regEx);
        Matcher matcher = pattern.matcher(xWPFParagraphText);//正则匹配字符串{****}
        System.out.println("begin");
        if (matcher.find()) {
            System.out.println("find");
            // 查找到有标签才执行替换
            int beginRunIndex = xWPFParagraph.searchText("{", new PositionInParagraph()).getBeginRun();// 标签开始run位置
            int endRunIndex = xWPFParagraph.searchText("}", new PositionInParagraph()).getEndRun();// 结束标签
            StringBuffer key = new StringBuffer();

            if (beginRunIndex == endRunIndex) {
                // {**}在一个run标签内
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.text();

                int beginIndex = beginRunText.indexOf("{");
                int endIndex = beginRunText.indexOf("}");
                int length = beginRunText.length();

                if (beginIndex == 0 && endIndex == length - 1) {
                    // 该run标签只有{**}
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    key.append(beginRunText.substring(1, endIndex));
                    insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
                    xWPFParagraph.removeRun(beginRunIndex + 1);
                } else {
                    // 该run标签为**{**}** 或者 **{**} 或者{**}**，替换key后，还需要加上原始key前后的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    key.append(beginRunText.substring(beginRunText.indexOf("{")+1, beginRunText.indexOf("}")));
                    String textString=beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(),parametersMap)
                            + beginRunText.substring(endIndex + 1);

                    insertNewRun.setText(textString);
                    xWPFParagraph.removeRun(beginRunIndex + 1);
                }

            }else {
                // {**}被分成多个run

                //先处理起始run标签,取得第一个{key}值
                XWPFRun beginRun = runs.get(beginRunIndex);
                String beginRunText = beginRun.text();
                int beginIndex = beginRunText.indexOf("{");
                if (beginRunText.length()>1  ) {
                    key.append(beginRunText.substring(beginIndex+1));
                }
                ArrayList<Integer> removeRunList = new ArrayList<Integer>();//需要移除的run
                //处理中间的run
                for (int i = beginRunIndex + 1; i < endRunIndex; i++) {
                    XWPFRun run = runs.get(i);
                    String runText = run.text();
                    key.append(runText);
                    removeRunList.add(i);
                }

                // 获取endRun中的key值
                XWPFRun endRun = runs.get(endRunIndex);
                String endRunText = endRun.text();
                int endIndex = endRunText.indexOf("}");
                //run中**}或者**}**
                if (endRunText.length()>1 && endIndex!=0) {
                    key.append(endRunText.substring(0,endIndex));
                }

                //*******************************************************************
                //取得key值后替换标签

                //先处理开始标签
                if (beginRunText.length()==2 ) {
                    // run标签内文本{
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
                    xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
                }else {
                    // 该run标签为**{**或者 {** ，替换key后，还需要加上原始key前的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
                    insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
                    // 设置文本
                    String textString=beginRunText.substring(0,beginRunText.indexOf("{"))+getValueBykey(key.toString(),parametersMap);
                    //	System.out.println(">>>>>"+textString);
                    //分行处理
                    if(textString.contains("@"))
                    {
                        String[] textStrings = textString.split("@");
                        for(int i = 0; i < textStrings.length;i++)
                        {
                            //System.out.println(">>>>>textStrings>>"+textStrings[i]);
                            insertNewRun.setText(textStrings[i]);
                            //insertNewRun.addCarriageReturn();
                            insertNewRun.addBreak();//换行
                        }
                    }
                    else if(textString.endsWith(".png"))
                    {
//                        CTInline inline = insertNewRun.getCTR().addNewDrawing().addNewInline();
//                        try {
//                            insertPicture(document,textString,
//                                    inline, 500,
//                                    200);
//                            document.createParagraph();// 添加回车换行
//                        } catch (Exception e) {
//                            // TODO Auto-generated catch block
//                            e.printStackTrace();
//                        }
                    } else {
                        insertNewRun.setText(textString);
                    }
                    xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
                }
                //处理结束标签
                if (endRunText.length()==1 ) {
                    // run标签内文本只有}
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    insertNewRun.setText("");
                    xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run

                }else {
                    // 该run标签为**}**或者 }** 或者**}，替换key后，还需要加上原始key后的文本
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
                    insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
                    // 设置文本
                    String textString=endRunText.substring(endRunText.indexOf("}")+1);
                    insertNewRun.setText(textString);
                    xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
                }

                //处理中间的run标签
                for (int i = 0; i < removeRunList.size(); i++) {
                    XWPFRun xWPFRun = runs.get(removeRunList.get(i));//原始run
                    XWPFRun insertNewRun = xWPFParagraph.insertNewRun(removeRunList.get(i));
                    insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());
                    insertNewRun.setText("");
                    xWPFParagraph.removeRun(removeRunList.get(i) + 1);//移除原始的run
                }

            }// 处理${**}被分成多个run

            replaceParagraph( xWPFParagraph, parametersMap);

        }//if 有标签

    }

    private static String getValueBykey(String key , Map<String, Object> params){
        System.out.println(key);
        Object o = params.get(key);
        if (null == o) {
            return "";
        }
        System.out.println(key + "=====" + o);
        return String.valueOf(o);
    }
}
